﻿using System.Collections;
using System.Windows;
using System.Windows.Media;

namespace Pilhas
{
    public class ControlVariables : Controls
    {
        /// <summary>
        /// cont -> number of elements in the stack
        /// contElem -> counter for the automatic labeling. Keeps the index of the element that will be inserted to the stack
        /// elemPopped -> contains the element that was popped from the stack        
        /// myStack -> a system stack that contains the elements of our stack 
        /// </summary>
        private static int cont = 0;
        private static int contElem = 0;
        private static int elemPopped = 0;
        private static Stack myStack = new Stack();

        /// <summary>
        /// Tests if the stack is full
        /// </summary>
        /// <returns></returns>
        internal static bool testOverflow()
        {
            if (cont != stackElements.numElements)
                cont++;
            else
            {
                txtTrace.writeTrace("Pilha Cheia!\nOperação não pode ser realizada. ", Brushes.Red);
                return true;
            }
            return false;
        }

        /// <summary>
        /// Tests if the stack is empty
        /// </summary>
        /// <returns></returns>
        internal static bool testUnderflow()
        {
            if (cont < 1)
            {
                txtTrace.writeTrace("Pilha Vazia!\nOperação não pode ser realizada. ", Brushes.Red);
                return true;
            }
            return false;
        }

        /// <summary>
        /// Updates the content of "myStack"
        /// </summary>
        /// <param name="bc"></param>
        internal static void updatemyStack(ButtonClicked bc)
        {
            if (bc.Equals(ButtonClicked.Push))
            {
                contElem++;
                myStack.Push(contElem);
            }
            else
            {
                cont--;
                elemPopped = (int)myStack.Pop();
            }
        }

        /// <summary>
        /// Updates trace information
        /// </summary>
        /// <param name="bc"></param>
        internal static void writeToTrace(ButtonClicked bc)
        {
           switch(bc)
           {
               case ButtonClicked.Push :
                   {
                       if (txtLetters.IsVisible)
                           txtTrace.writeTrace("Empilha elemento " + elemLabels.getContent(cont - 1), Brushes.Goldenrod);
                       else txtTrace.writeTrace("Empilha elemento " + contElem.ToString(), Brushes.Goldenrod);
                   }
                   break;
               case ButtonClicked.Pop :
                   {
                       if (txtLetters.IsVisible)
                           txtTrace.writeTrace("Remove elemento " + elemLabels.getContent(cont), Brushes.AntiqueWhite);
                       else txtTrace.writeTrace("Remove elemento " + elemPopped.ToString(), Brushes.AntiqueWhite);
                   }
                   break;
               case ButtonClicked.Create: { txtTrace.writeTrace("\nCria nova pilha vazia", Brushes.RoyalBlue); }
                   break;
               case ButtonClicked.Destroy: { txtTrace.writeTrace("\nDestrói a pilha", Brushes.RoyalBlue); }
                   break;
           }
        }

        /// <summary>
        /// Sets the ellipses, the labels and the blueArrow to hidden
        /// </summary>
        internal static void setAllHidden()
        {
            stackElements.setAllHidden();
            elemLabels.setAllHidden();
            blueArrow.Visibility = Visibility.Hidden;
        }
        
        /// <summary>
        /// Updates the bluArrow margin so that it is always poiting to the element at the top of the stack
        /// </summary>
        internal static void updateImageMargin()
        {
            blueArrow.Margin = new Thickness(5, (393 / (stackElements.numElements)) * (stackElements.numElements - (cont - 1) - 1), 0, (393 / (stackElements.numElements)) * (cont - 1));
        }

        /// <summary>
        /// Sets the elements visibility accordingly to the button clicked
        /// </summary>
        /// <param name="bc"></param>
        internal static void setElementsVisibility(ButtonClicked bc)
        {
            switch (bc)
            {
                case ButtonClicked.Create:setAllHidden();
                    break;
                case ButtonClicked.Destroy:setAllHidden();
                    break;
                case ButtonClicked.Pop:
                    {
                        stackElements.setVisibility(cont, Visibility.Hidden);
                        elemLabels.setVisibility(cont, Visibility.Hidden);

                        if (cont != 0)
                            blueArrow.Margin = new Thickness(5, 39 * (stackElements.numElements - (cont - 1) - 1), 0, 39 * (cont - 1));
                        else blueArrow.Visibility = Visibility.Hidden;
                    }
                    break;
                case ButtonClicked.Push:
                    {
                        if (!blueArrow.IsVisible)
                            blueArrow.Visibility = Visibility.Visible;

                        elemLabels.setVisibility(cont - 1, Visibility.Visible);
                        stackElements.setVisibility(cont - 1, Visibility.Visible);
                    }
                    break;
            }
        }

        /// <summary>
        /// Sets elements labels content. If the "useLetters" TextBox is visible then custom labels will be
        /// used. Otherwise, an automatic label will be applyed to the element.
        /// </summary>
        /// <returns></returns>
        internal static bool setLabelsContent()
        {
            if (txtLetters.IsVisible)
            {
                if (txtLetters.Text.Equals(""))
                {
                    cont--;
                    MessageBox.Show("Você deve informar o rótulo a ser inserido.");
                    return false;
                }

                elemLabels.setContent(cont - 1, txtLetters.Text.ToString());
                for (int i = 0; i < cont; i++)
                    elemLabels.setVisibility(i, Visibility.Visible);
                
                txtLetters.Text = "";                
            }
            else elemLabels.setContent(cont - 1, contElem.ToString());

            return true;
        }

        /// <summary>
        /// Resets the counters
        /// </summary>
        internal static void resetCounters()
        {
            cont = 0;
            contElem = 0;
        }

        
    }
}
